/*  ------------------------------------------------------------------------
	NQ Common Services Library
	
	Homepage: http://www.awzhome.de/
	------------------------------------------------------------------------
	
	The contents of this file are subject to the Mozilla Public License
	Version 1.1 (the "License"); you may not use this file except in
	compliance with the License. You may obtain a copy of the License at
	http://www.mozilla.org/MPL/
	
	Software distributed under the License is distributed on an "AS IS"
	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	License for the specific language governing rights and limitations
	under the License.
   
	The Original Code is code of NQ Common Services Library.

	The Initial Developer of the Original Code is Andreas Weizel.
	Portions created by the Initial Developer are
	Copyright (C) 2006-2010 Andreas Weizel. All Rights Reserved.
	
	Contributor(s): (none)
	
	Alternatively, the contents of this file may be used under the terms
	of the GNU General Public License Version 2.0 or later (the "GPL"),
	or the GNU Lesser General Public License Version 2.1 or later (the
	"LGPL"), in which case the provisions of the GPL or the LGPL are
	applicable instead of those above. If you wish to allow use of your
	version of this file only under the terms of the GPL or the LGPL and
	not to allow others to use your version of this file under the MPL,
	indicate your decision by deleting the provisions above and replace
	them with the notice and other provisions required by the GPL or the
	LGPL. If you do not delete the provisions above, a recipient may use
	your version of this file under the terms of any of the MPL, the GPL
	or the LGPL.
	------------------------------------------------------------------------
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using AWZhome.NQ.Core;
using AWZhome.NQ.Core.Fluent;
using AWZhome.NQ.CommonServices.Visual;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using System.Windows.Data;

namespace AWZhome.NQ.CommonServices
{
	[NQExportedService(Category = NQHostMode.GUI)]
	public partial class PreferenceGUIService : Services.IPreferenceGUIService
	{
		private IView activeView = null;

		private IPersistManager servPersist = null;
		private IResourceManager servRes = null;

		private PreferenceWindow _prefWindow = null;
		private Dictionary<string, IView> _views = new Dictionary<string, IView>();
		private ObservableCollection<IView> _viewControls = new ObservableCollection<IView>();

		public PreferenceGUIService(IContainer parent)
		{
			// Create preference window instance and set the event handlers
			_prefWindow = new PreferenceWindow();
			_prefWindow.ViewListBox.SelectionChanged += new System.Windows.Controls.SelectionChangedEventHandler(ViewListBox_SelectionChanged);
			_prefWindow.Closed += new EventHandler(_prefWindow_Closed);
			_prefWindow.OKButton.Click += new RoutedEventHandler(OKButton_Click);
			_prefWindow.CancelButton.Click += new RoutedEventHandler(CancelButton_Click);
			_prefWindow.ApplyButton.Click += new RoutedEventHandler(ApplyButton_Click);
			((CollectionViewSource) _prefWindow.FindResource("ViewServiceCollectionSource")).Source = _viewControls;

			// Get references of needed services
			servPersist = ServiceCore
				.Get<Services.IPersistService>()
				.To;
			servRes = ServiceCore
				.Get<Services.IResourceService>()
				.To;

			// Add all attached views
			IView[] attachedViews = ServiceCore
				.RetrieveAttached<IView>(CommonAttachLists.PreferenceUI_PrefViews)
				.DependentOn<ISession>(null)
				.To;
			if (attachedViews != null)
			{
				foreach (IView view in attachedViews)
				{
					view.Initialize("");
					view.LoadContents();
					this.AddView(view, false);
				}
			}

			// Read settings
			ConfigData splitterPos = servPersist.GetSetting("NQCS", "prefSplitterPos", true);
			ConfigData lastActiveView = servPersist.GetSetting("NQCS", "prefLastView", true);
			ConfigData windowRect = servPersist.GetSetting("NQCS", "prefWindowRect", true);

			if ((windowRect != null) && !windowRect.IsEmpty)
			{
				Rect windowrect = windowRect.AsRect().Value;
				_prefWindow.Top = windowrect.Top;
				_prefWindow.Left = windowrect.Left;
				_prefWindow.Height = windowrect.Height;
				_prefWindow.Width = windowrect.Width;
			}
			if (splitterPos != null)
			{
				_prefWindow.InnerGrid.ColumnDefinitions[0].Width = (GridLength) (new GridLengthConverter()).ConvertFromString(splitterPos.RawData);
			}
			else
			{
				_prefWindow.InnerGrid.ColumnDefinitions[0].Width = new GridLength(_prefWindow.Width / 4);
			}
			if ((lastActiveView != null) && _views.ContainsKey(lastActiveView.AsString()))
			{
				this.ActiveView = _views[lastActiveView.AsString()];
			}
			else
			{
				// Activate the first list item
				if (_prefWindow.ViewListBox.Items.Count > 0)
				{
					_prefWindow.ViewListBox.SelectedIndex = 0;
				}
			}

			// Show the preference window
			parent.ShowModalDialog(_prefWindow);
		}

		#region INQViewManagerService Members

		public event System.EventHandler<ActiveViewChangedEventArgs> ActiveViewChanged;

		public void AddView(IView newView)
		{
			AddView(newView, true);
		}

		public void AddView(IView newView, bool activate)
		{
			if (newView != null)
			{
				if (!_views.ContainsKey(newView.Name))
				{
					// Add the view to internal lists
					_views.Add(newView.Name, newView);
					_viewControls.Add(newView);

					// Set the view active, if necessary
					if (activate)
					{
						this.ActiveView = newView;
					}
				}
			}
		}

		public void RemoveView(string viewName)
		{
			if (_views.ContainsKey(viewName))
			{
				IView delview = _views[viewName];

				if (delview.CanBeClosed)
				{
					if (_views.Count == 1)
					{
						// Clear active view reference
						this.ActiveView = null;
					}

					_views.Remove(viewName);
					_viewControls.Remove(delview);
				}
			}
		}

		public void UpdateView(IView view, bool internalChange)
		{
			// In preferences dialog it's not necessary to update the views dynamically
		}

		public void MoveView(IView view, IViewManager destManager)
		{
			// In preference dialog it's not necessary to move the views to other view managers
		}

		public int CountByDisplayMode(ViewDisplayMode displayMode)
		{
			return this.Count;
		}

		public void LoadSettings()
		{
			// Do nothing here
		}

		public void SaveSettings()
		{
			// Do nothing here
		}

		public IView ActiveView
		{
			get
			{
				return activeView;
			}
			set
			{
				if (value != null)
				{
					// Activate the list item (current view instance)
					activeView = value;
					_prefWindow.ViewListBox.SelectedItem = activeView;
				}
				else
				{
					OnActiveViewChanged(activeView, null);
					activeView = null;
				}
			}
		}

		public ISession ActiveSession
		{
			get
			{
				if (activeView != null)
				{
					return activeView.Session;
				}
				else
				{
					return null;
				}
			}
		}

		public IContainer Container
		{
			get
			{
				return null;
			}
		}

		#endregion

		#region INQCollectionService<string, INQViewServiceBase> Members

		public IView this[string key]
		{
			get
			{
				if (_views.ContainsKey(key))
				{
					return _views[key];
				}
				else
				{
					return null;
				}
			}
		}

		public IEnumerator<IView> GetEnumerator()
		{
			return ((IEnumerable<IView>) _views.Values).GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return ((System.Collections.IEnumerable) _views.Values).GetEnumerator();
		}

		public int Count
		{
			get
			{
				return _views.Count;
			}
		}

		#endregion

		#region Private methods

		private void _prefWindow_Closed(object sender, EventArgs e)
		{
			// Save the settings
			servPersist.SetSetting("NQCS", "prefSplitterPos",
				new ConfigData().FromString((new GridLengthConverter()).ConvertToString(_prefWindow.InnerGrid.ColumnDefinitions[0].Width)), true);
			if (this.ActiveView != null)
			{
				servPersist.SetSetting("NQCS", "prefLastView", new ConfigData().FromString(this.ActiveView.Name), true);
			}
			Rect boundRect = new Rect(_prefWindow.Left, _prefWindow.Top, _prefWindow.Width, _prefWindow.Height);
			servPersist.SetSetting("NQCS", "prefWindowRect", new ConfigData().FromRect(boundRect), true);
		}

		private void ApplyButton_Click(object sender, RoutedEventArgs e)
		{
			// Enforce all views to save their settings
			foreach (IView view in _views.Values)
			{
				view.SaveContents(ViewSaveReason.SaveRunningState);
			}
		}

		private void CancelButton_Click(object sender, RoutedEventArgs e)
		{
			// Close the dialog
			_prefWindow.Close();
		}

		private void OKButton_Click(object sender, RoutedEventArgs e)
		{
			// OK = Apply + Cancel
			ApplyButton_Click(sender, e);
			CancelButton_Click(sender, e);
		}

		private void ViewListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
		{
			IView oldview = null;
			IView selview = null;

			if (_prefWindow.ViewListBox.SelectedItem != null)
			{
				// Show the view contents
				_prefWindow.ViewInnerSpaceGrid.Children.Clear();
				selview = _prefWindow.ViewListBox.SelectedItem as IView;
				if (selview != null)
				{
					if (selview.DisplayedObject is System.Windows.Forms.Control)
					{
						// The view's graphical control is a WinForms control, we need a WindowsFormsHost around it
						WindowsFormsHost winFormsHost = new WindowsFormsHost();
						winFormsHost.Child = (System.Windows.Forms.Control) selview.DisplayedObject;
						_prefWindow.ViewInnerSpaceGrid.Children.Add(winFormsHost);
					}
					else
					{
						// The view's graphical control is a standard WPF control
						Control dispControl = selview.DisplayedObject as Control;
						if (dispControl != null)
						{
							_prefWindow.ViewInnerSpaceGrid.Children.Add(dispControl);
						}
					}
				}

				oldview = activeView;
				if (oldview != null)
				{
					oldview.Deactivate(selview);
				}
				activeView = selview;
				if (selview != null)
				{
					selview.Activate(oldview);
				}

				OnActiveViewChanged(oldview, selview);
			}
		}

		private void OnActiveViewChanged(IView oldview, IView newview)
		{
			if (this.ActiveViewChanged != null)
			{
				this.ActiveViewChanged(this, new ActiveViewChangedEventArgs(oldview, newview));
			}
		}

		#endregion
	}
}